#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/5/24 11:38
# @Author  : wangjiamin
# @File    : MangoDownload.py
# @Software: PyCharm
# @Mail    : wangjiamin@pachira.com
import os
import pdb
import socket
import ftplib
from enum import Enum
import re
import shutil
import configparser

mongo_config = configparser.ConfigParser()
mongo_config.read('conf/mongo.ini')



class FileType(Enum):
    FILE_TYPE_CONFIG = 0
    FILE_TYPE_CASE_LIST = 1


class PathType(Enum):
    PATH_TYPE_ABSOLUTE = 0
    PATH_TYPE_RELATIVE = 1


class MyFTP:
    def __init__(self):
        self.file_list = None
        self.host = mongo_config.get('ftp', 'host')
        self.port = int(mongo_config.get('ftp', 'port'))
        self.user = mongo_config.get('ftp', 'username')
        self.pwd = mongo_config.get('ftp', 'passwd')
        self.remote_dir = mongo_config.get('ftp', 'remoteDir')
        self.ftp = ftplib.FTP()
        self.ftp.encoding = "utf-8"

    def __del__(self):
        if self.ftp:
            self.ftp.close()

    def login(self):
        ftp = self.ftp
        try:
            timeout = 10000
            socket.setdefaulttimeout(timeout)
            ftp.set_pasv(True)
            ftp.connect(self.host, self.port)
            print('\n==========成功连接到 %s==========' % self.host)
            ftp.login(self.user, self.pwd)
        except Exception as e:
            print(f'==========连接或登陆失败: {e}==========')
        try:
            ftp.cwd(self.remote_dir)
        except Exception as e:
            print(f'==========切换目录[{self.remote_dir}]失败: {e}==========')

    def is_same_size(self, local_file, remote_file):
        try:
            remote_file_size = self.ftp.size(remote_file)
        except Exception as e:
            print('get remote file size error:', e)
            remote_file_size = -1
        try:
            local_file_size = os.path.getsize(local_file)
        except Exception as e:
            # print('get local file size error:', e)
            local_file_size = -1
        if remote_file_size != local_file_size:
            return 0
        else:
            return 1

    def download_file(self, local_file, remote_file, pathType, file_type):
        filepath = None
        local_dir = os.path.dirname(local_file)
        if not os.path.isdir(local_dir):
            os.makedirs(local_dir)
        if pathType.value == 0:
            filepath = remote_file
        elif pathType.value == 1:
            filepath = os.path.join(local_dir, remote_file)
        if self.is_same_size(local_file, remote_file):
            return
        else:
            try:
                file_handler = open(local_file, 'wb')
                self.ftp.retrbinary('RETR %s' % remote_file, file_handler.write)
                file_handler.close()
                if file_type.value == 0:
                    print(">>>>>>>>>>文件 %s 下载成功" % filepath)
                return 0
            except Exception as e:
                print(f">>>>>>>>>>文件[{filepath}]下载失败:{e}")
                return -1

    def download_dir(self, local_dir, remote_dir, file_type):
        try:
            self.ftp.cwd(remote_dir)
        except Exception as e:
            print("failed to enter remote directory:", e)
            return -1
        if not os.path.isdir(local_dir):
            os.makedirs(local_dir)
        self.file_list = []
        self.ftp.dir(self.get_file_list)
        remote_names = self.file_list
        for item in remote_names:
            filetype = item[0]
            filename = item[1]
            local = os.path.join(local_dir, filename)
            if filetype == 'd':
                self.download_dir(local, filename, file_type)
            elif filetype == '-':
                self.download_file(local, filename, PathType.PATH_TYPE_RELATIVE, file_type)
        print("==========目录 %s 下载完成" % local_dir)
        self.ftp.cwd("..")
        return 0

    def get_file_list(self, line):
        file_arr = self.get_file_name(line)
        if file_arr[1] not in ['.', '..']:
            self.file_list.append(file_arr)

    @staticmethod
    def get_file_name(line):
        pos = line.rfind(' ')
        while line[pos] != ' ':
            pos += 1
        while line[pos] == ' ':
            pos += 1
        file_arr = [line[0], line[pos:]]
        return file_arr


class Download:
    config = None
    case = None
    config_list = []
    case_list = []

    def __init__(self):
        self.ftp = MyFTP()
        self.ftp.login()

    def __reset(self):
        self.config = None
        self.case = None

    def is_need_download(self, file_type):
        if file_type.value == 0:
            if self.config in self.config_list:
                return False
            return True
        if file_type.value == 1:
            if self.case in self.case_list:
                return False
            return True

    def start_download(self, file, file_type):
        self.__reset()
        try:
            if file_type == FileType.FILE_TYPE_CONFIG:
                self.config = file
                self.parse_config()
                self.config_list.append(file)
            elif file_type == FileType.FILE_TYPE_CASE_LIST:
                self.case = file
                self.parse_case_list()
                self.case_list.append(file)
        except ftplib.all_errors as e:
            print("FTP下载错误:", e)

    def parse_config(self):
        try:
            with open(self.config) as fp:
                lines = fp.readlines()
        except IOError:
            print("The config[%s] is not exists!" % self.config)
        else:
            for line in lines:
                if "FTP_RES" in line:
                    res_path = line.split('=')[1].strip().replace('"', '').replace("'", '').replace(";", '')
                    self.ftp.ftp.cwd("/home/gongxiang/asr/Boloo/").strip()
                    if os.path.exists(res_path) and os.path.isdir(res_path):
                        print("清除本地资源: ", res_path)
                        shutil.rmtree(res_path)
                    ret = self.ftp.download_dir("%s" % res_path, res_path, FileType.FILE_TYPE_CONFIG)
                    if ret != 0:
                        self.ftp.download_file("%s" % res_path, res_path, PathType.PATH_TYPE_ABSOLUTE, FileType.FILE_TYPE_CONFIG)

    def parse_case_list(self):
        voice_format = None
        try:
            with open(self.case) as fp:
                lines = fp.readlines()
        except IOError:
            print("The caselist[%s] is not exists!" % self.case)
        else:
            for line in lines:
                if "@VOICE_PATH" in line:
                    voice_format = line.replace("@VOICE_PATH:", "").strip()
                if line.isspace() or line[0] == "#" or line[:2] == "//":
                    continue
                match = re.search(r'voice:(.*?)\t', line)
                if match:
                    voice_path = match.group(1).split(";")[0]
                    if voice_format and voice_path:
                        voice_path = voice_path.replace("VOICE_PATH", voice_format)
                    if "FTP_RES" in voice_path:
                        self.ftp.ftp.cwd("/home/gongxiang/asr/Boloo/")
                        ret = self.ftp.download_file("%s" % voice_path, voice_path, PathType.PATH_TYPE_ABSOLUTE, FileType.FILE_TYPE_CASE_LIST)
                        if ret == 0:
                            print(">>>>>>>>>>文件 %s 下载成功" % voice_path)


if __name__ == '__main__':
    download = Download()
    download.start_download("file.txt", FileType.FILE_TYPE_CONFIG)

